package org.sqldroid;

import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.Array;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.Date;
import java.sql.NClob;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.Ref;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.RowId;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import android.content.ContentValues;
import android.database.Cursor;
import android.util.Log;

public class SqldroidPreparedStatement implements PreparedStatement {

	SQLiteDatabase db;
	SqldroidConnection sqldroidConnection;
	SqldroidResultSet rs = null;
	String sql;
	ContentValues cv = new ContentValues();
	ArrayList<Object> l = new ArrayList<Object>();

	public SqldroidPreparedStatement(final String sql, final SqldroidConnection sqldroid) {
		Log.i("SQLDRoid", "new SqlDRoid prepared statement from " + sqldroid);
		sqldroidConnection = sqldroid;
		db = sqldroid.getDb();
		this.sql = sql;
	}

	private void ensureCap(final int n) {
	}

	private void setObj(int n, final Object obj) {

		// prapred statments count from 1, we count from 0 (in array)
		n--;

		// if arraylist is too small we add till it's grand enough
		// btw, why ain't there a l.setSize(n)?

		final int additions = n - l.size() + 1;
		System.out.println("adding " + additions + " elements");
		for (int i = 0; i < additions; i++) {
			System.out.println("ADD NULL");
			l.add(null);
		}

		System.out.println("n = " + n + " size now " + l.size() + " we @ " + n);
		l.set(n, obj);
		System.out.println("POST set n = " + n + " size now " + l.size() + " we @ " + n);
	}

	public void addBatch(final String sql) throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void cancel() throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void clearBatch() throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void clearWarnings() throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void close() throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
	}

	private String[] makeArgListQueryString() {
		// convert our parameter list objects to strings
		final List<String> strList = new ArrayList<String>();

		for (final Object o : l) {
			strList.add(o.toString());
		}

		return strList.toArray(new String[1]);
	}

	private Object[] makeArgListQueryObject() {
		return l.toArray();
	}

	public boolean execute() throws SQLException {
		boolean ok = false;
		try {
			System.out.print("Executing \"" + sql + "\" on " + db + " with args ");

			db.execSQL(sql, makeArgListQueryObject());
			ok = true;
		} catch (final android.database.SQLException e) {
			System.out.println("SqlDRoid exception: ");
			e.printStackTrace();
		}

		return ok;
	}

	public ResultSet executeQuery() throws SQLException {
		Log.d("sqldroid", "executeQuery " + sql);
		// when querying, all ? values must be converted to Strings for some
		// reason
		final Cursor c = db.rawQuery(sql, makeArgListQueryString());
		Log.d("sqldroid", "executeQuery " + 2);
		rs = new SqldroidResultSet(c);
		Log.d("sqldroid", "executeQuery " + 3);
		return rs;
	}

	public int executeUpdate() throws SQLException {
		// TODO we can't count the actual number of updates .... :S
		return execute() ? 1 : 0;
	}

	public boolean execute(final String sql) throws SQLException {

		this.sql = sql;

		return execute();
	}

	public boolean execute(final String sql, final int autoGeneratedKeys)
			throws SQLException {

		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

		return false;
	}

	public boolean execute(final String sql, final int[] columnIndexes) throws SQLException {

		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

		return false;
	}

	public boolean execute(final String sql, final String[] columnNames)
			throws SQLException {

		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

		return false;
	}

	public int[] executeBatch() throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return null;
	}

	public ResultSet executeQuery(final String sql) throws SQLException {

		this.sql = sql;
		return executeQuery();
	}

	public int executeUpdate(final String sql) throws SQLException {
		db.execSQL(sql);

		return 0;
	}

	public int executeUpdate(final String sql, final int autoGeneratedKeys)
			throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public int executeUpdate(final String sql, final int[] columnIndexes)
			throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public int executeUpdate(final String sql, final String[] columnNames)
			throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public Connection getConnection() throws SQLException {
		return sqldroidConnection;
	}

	public int getFetchDirection() throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public int getFetchSize() throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public ResultSet getGeneratedKeys() throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return null;
	}

	public int getMaxFieldSize() throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public int getMaxRows() throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public boolean getMoreResults() throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return false;
	}

	public boolean getMoreResults(final int current) throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return false;
	}

	public int getQueryTimeout() throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public ResultSet getResultSet() throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return null;
	}

	public int getResultSetConcurrency() throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public int getResultSetHoldability() throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public int getResultSetType() throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public int getUpdateCount() throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return 0;
	}

	public SQLWarning getWarnings() throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return null;
	}

	public void setCursorName(final String name) throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setEscapeProcessing(final boolean enable) throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setFetchDirection(final int direction) throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setFetchSize(final int rows) throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setMaxFieldSize(final int max) throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setMaxRows(final int max) throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setQueryTimeout(final int seconds) throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void addBatch() throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void clearParameters() throws SQLException {
		l = new ArrayList<Object>();
	}

	public ResultSetMetaData getMetaData() throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return null;
	}

	public ParameterMetaData getParameterMetaData() throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
		return null;
	}

	public void setArray(final int parameterIndex, final Array theArray)
			throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setAsciiStream(final int parameterIndex, final InputStream theInputStream,
			final int length) throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setBigDecimal(final int parameterIndex, final BigDecimal theBigDecimal)
			throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setBinaryStream(final int parameterIndex, final InputStream theInputStream,
			final int length) throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setBlob(final int parameterIndex, final Blob theBlob) throws SQLException {

		ensureCap(parameterIndex);
		setObj(parameterIndex, theBlob.getBytes(0, (int) theBlob.length()));

	}

	public void setBoolean(final int parameterIndex, final boolean theBoolean)
			throws SQLException {

		ensureCap(parameterIndex);
		setObj(parameterIndex, theBoolean);

	}

	public void setByte(final int parameterIndex, final byte theByte) throws SQLException {

		ensureCap(parameterIndex);
		setObj(parameterIndex, theByte);

	}

	public void setBytes(final int parameterIndex, final byte[] theBytes)
			throws SQLException {
		ensureCap(parameterIndex);
		setObj(parameterIndex, theBytes);
	}

	public void setCharacterStream(final int parameterIndex, final Reader reader, final int length)
			throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setClob(final int parameterIndex, final Clob theClob) throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setDate(final int parameterIndex, final Date theDate) throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());
	}

	public void setDate(final int parameterIndex, final Date theDate, final Calendar cal)
			throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setDouble(final int parameterIndex, final double theDouble)
			throws SQLException {
		ensureCap(parameterIndex);
		setObj(parameterIndex, new Double(theDouble));
	}

	public void setFloat(final int parameterIndex, final float theFloat)
			throws SQLException {
		ensureCap(parameterIndex);
		setObj(parameterIndex, new Double(theFloat));

	}

	public void setInt(final int parameterIndex, final int theInt) throws SQLException {
		ensureCap(parameterIndex);
		setObj(parameterIndex, new Long(theInt));

	}

	public void setLong(final int parameterIndex, final long theLong) throws SQLException {
		ensureCap(parameterIndex);
		setObj(parameterIndex, new Long(theLong));

	}

	public void setNull(final int parameterIndex, final int sqlType) throws SQLException {
		ensureCap(parameterIndex);
		setObj(parameterIndex, null);

	}

	public void setNull(final int paramIndex, final int sqlType, final String typeName)
			throws SQLException {
		ensureCap(paramIndex);
		setObj(paramIndex, null);

	}

	public void setObject(final int parameterIndex, final Object theObject)
			throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setObject(final int parameterIndex, final Object theObject,
			final int targetSqlType) throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setObject(final int parameterIndex, final Object theObject,
			final int targetSqlType, final int scale) throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setRef(final int parameterIndex, final Ref theRef) throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setShort(final int parameterIndex, final short theShort)
			throws SQLException {
		ensureCap(parameterIndex);
		setObj(parameterIndex, new Long(theShort));

	}

	public void setString(final int parameterIndex, final String theString) {
		ensureCap(parameterIndex);
		setObj(parameterIndex, theString);

	}

	public void setTime(final int parameterIndex, final Time theTime) throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setTime(final int parameterIndex, final Time theTime, final Calendar cal)
			throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setTimestamp(final int parameterIndex, final Timestamp theTimestamp)
			throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setTimestamp(final int parameterIndex, final Timestamp theTimestamp,
			final Calendar cal) throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setURL(final int parameterIndex, final URL theURL) throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public void setUnicodeStream(final int parameterIndex,
			final InputStream theInputStream, final int length) throws SQLException {
		System.err.println(" ********************* not implemented @ "
				+ DebugPrinter.getFileName() + " line "
				+ DebugPrinter.getLineNumber());

	}

	public boolean isClosed() throws SQLException {
		// TODO Auto-generated method stub
		return false;
	}

	public boolean isPoolable() throws SQLException {
		// TODO Auto-generated method stub
		return false;
	}

	public void setPoolable(final boolean poolable) throws SQLException {
		// TODO Auto-generated method stub

	}

	public boolean isWrapperFor(final Class<?> arg0) throws SQLException {
		// TODO Auto-generated method stub
		return false;
	}

	public <T> T unwrap(final Class<T> arg0) throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

	public void setAsciiStream(final int parameterIndex, final InputStream inputStream)
			throws SQLException {
		// TODO Auto-generated method stub

	}

	public void setAsciiStream(final int parameterIndex, final InputStream inputStream,
			final long length) throws SQLException {
		// TODO Auto-generated method stub

	}

	public void setBinaryStream(final int parameterIndex, final InputStream inputStream)
			throws SQLException {
		// TODO Auto-generated method stub

	}

	public void setBinaryStream(final int parameterIndex, final InputStream inputStream,
			final long length) throws SQLException {
		// TODO Auto-generated method stub

	}

	public void setBlob(final int parameterIndex, final InputStream inputStream)
			throws SQLException {
		// TODO Auto-generated method stub

	}

	public void setBlob(final int parameterIndex, final InputStream inputStream, final long length)
			throws SQLException {
		// TODO Auto-generated method stub

	}

	public void setCharacterStream(final int parameterIndex, final Reader reader)
			throws SQLException {
		// TODO Auto-generated method stub

	}

	public void setCharacterStream(final int parameterIndex, final Reader reader,
			final long length) throws SQLException {
		// TODO Auto-generated method stub

	}

	public void setClob(final int parameterIndex, final Reader reader) throws SQLException {
		// TODO Auto-generated method stub

	}

	public void setClob(final int parameterIndex, final Reader reader, final long length)
			throws SQLException {
		// TODO Auto-generated method stub

	}

	public void setNCharacterStream(final int parameterIndex, final Reader reader)
			throws SQLException {
		// TODO Auto-generated method stub

	}

	public void setNCharacterStream(final int parameterIndex, final Reader reader,
			final long length) throws SQLException {
		// TODO Auto-generated method stub

	}

	public void setNClob(final int parameterIndex, final NClob value) throws SQLException {
		// TODO Auto-generated method stub

	}

	public void setNClob(final int parameterIndex, final Reader reader) throws SQLException {
		// TODO Auto-generated method stub

	}

	public void setNClob(final int parameterIndex, final Reader reader, final long length)
			throws SQLException {
		// TODO Auto-generated method stub

	}

	public void setNString(final int parameterIndex, final String theString)
			throws SQLException {
		// TODO Auto-generated method stub

	}

	public void setRowId(final int parameterIndex, final RowId theRowId)
			throws SQLException {
		// TODO Auto-generated method stub

	}

	public void setSQLXML(final int parameterIndex, final SQLXML xmlObject)
			throws SQLException {
		// TODO Auto-generated method stub

	}

}
